package installer

import (
	"context"
	"fmt"
	"os/exec"
	"strings"

	"gitee.com/liumou_site/glpm"
	"go.uber.org/zap"
)

// DependencyManager 依赖管理器
type DependencyManager struct {
	packageManager glpm.PackageManager
	ctx            context.Context
}

// NewDependencyManager 创建依赖管理器
func NewDependencyManager() *DependencyManager {
	ctx := context.Background()

	// 获取推荐的包管理器
	recommendedManager := glpm.GetRecommendedManager()

	// 创建包管理器配置
	config := glpm.NewManagerConfig()
	config.Sudo = true // 需要sudo权限

	// 获取包管理器实例
	pm, err := glpm.GetPackageManager(recommendedManager, config)
	if err != nil {
		zap.L().Warn("创建glpm包管理器失败，将使用备用方案", zap.Error(err))
		return &DependencyManager{}
	}

	return &DependencyManager{
		packageManager: pm,
		ctx:            ctx,
	}
}

// EnsureDependencies 确保依赖存在（直接实现，无二次封装）
func (d *DependencyManager) EnsureDependencies(installMissing bool) (bool, string) {
	zap.L().Info("检查编译依赖")

	// 定义必要的编译工具
	dependencies := []string{
		"gcc", "make", "autoconf", "automake", "libtool",
		"tar", "gzip", "wget", "curl",
	}

	missingDeps := []string{}
	
	// 检查每个依赖
	for _, dep := range dependencies {
		// 将命令名转换为对应的包名
		packageName := d.getPackageName(dep)
		
		// 优先使用glpm检查包是否已安装
		if d.packageManager != nil {
			installed, err := d.packageManager.IsInstalled(d.ctx, packageName)
			if err != nil {
				zap.L().Warn("检查包安装状态时出错", zap.String("package", packageName), zap.Error(err))
				// 如果glpm检查失败，回退到命令检查
				if !d.checkCommandExists(dep) {
					missingDeps = append(missingDeps, dep)
				}
				continue
			}
			
			if !installed {
				missingDeps = append(missingDeps, dep)
			}
		} else {
			// glpm不可用，使用命令检查
			if !d.checkCommandExists(dep) {
				missingDeps = append(missingDeps, dep)
			}
		}
	}
	
	// 如果没有缺失的依赖
	if len(missingDeps) == 0 {
		zap.L().Info("所有编译依赖检查通过")
		return true, "所有依赖已安装"
	}
	
	// 处理缺失的依赖
	missingList := strings.Join(missingDeps, ", ")
	message := fmt.Sprintf("缺少以下依赖: %s", missingList)
	
	if installMissing {
		zap.L().Warn("尝试安装缺失的依赖", zap.String("missingList", missingList))
		if d.installDependenciesWithGLPM(missingDeps) {
			zap.L().Info("依赖安装成功")
			return true, "依赖安装成功"
		} else {
			zap.L().Error("依赖安装失败")
			return false, fmt.Sprintf("依赖安装失败: %s", missingList)
		}
	} else {
		zap.L().Error("缺少依赖且未启用自动安装", zap.String("missingList", missingList))
		return false, message
	}
}

// installDependenciesWithGLPM 使用glpm安装依赖
func (d *DependencyManager) installDependenciesWithGLPM(dependencies []string) bool {
	zap.L().Info("使用glpm安装依赖", zap.Strings("dependencies", dependencies))

	// 将命令名转换为包名
	packageNames := []string{}
	for _, dep := range dependencies {
		packageNames = append(packageNames, d.getPackageName(dep))
	}

	// 首先更新包列表
	if err := d.packageManager.Update(d.ctx); err != nil {
		zap.L().Warn("更新包列表失败", zap.Error(err))
	}

	// 安装包
	if err := d.packageManager.Install(d.ctx, packageNames); err != nil {
		zap.L().Error("使用glpm安装依赖失败", zap.Error(err))
		return false
	}

	zap.L().Info("glpm依赖安装成功")
	return true
}

// getPackageName 获取命令对应的包名
func (d *DependencyManager) getPackageName(command string) string {
	packageMap := map[string]string{
		"gcc":      "gcc",
		"make":     "make",
		"autoconf": "autoconf",
		"automake": "automake",
		"libtool":  "libtool",
		"tar":      "tar",
		"gzip":     "gzip",
		"wget":     "wget",
		"curl":     "curl",
	}

	if pkgName, ok := packageMap[command]; ok {
		return pkgName
	}

	return command
}

// checkCommandExists 检查命令是否存在
func (d *DependencyManager) checkCommandExists(command string) bool {
	cmd := exec.Command("which", command)
	return cmd.Run() == nil
}
